package top.wuchu.rpc.registry;

import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.pojo.Instance;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import top.wuchu.rpc.enumeration.RpcError;
import top.wuchu.rpc.exception.RpcException;
import top.wuchu.rpc.loadbalancer.LoadBalancer;
import top.wuchu.rpc.loadbalancer.RandomLoadBalancer;
import top.wuchu.rpc.util.NacosUtil;

import java.net.InetSocketAddress;
import java.util.List;

/**
 * @author Wuchu
 */
public class NacosServiceDiscovery implements ServiceDiscovery {

    private static final Logger logger = LoggerFactory.getLogger(NacosServiceDiscovery.class);

    private final LoadBalancer loadBalancer;

    /**
     *  根据负载均衡的算法进行服务发现
     * @param loadBalancer
     */
    public NacosServiceDiscovery(LoadBalancer loadBalancer) {
        // 如果不指定负载均衡算法，那么默认使用随机算法
        if(loadBalancer == null) {
            this.loadBalancer = new RandomLoadBalancer();
        } else{
            this.loadBalancer = loadBalancer;
        }
    }

    /**
     * 根据选择的负载均衡算法进行服务的选择
     * @param serviceName 服务名称
     * @return 服务所在的InetSocketAddress
     */
    @Override
    public InetSocketAddress lookupService(String serviceName) {
        try {
            List<Instance> instances = NacosUtil.getAllInstance(serviceName);
            if(instances.size() == 0) {
                logger.error("找不到对应的服务: " + serviceName);
                throw new RpcException(RpcError.SERVICE_NOT_FOUND);
            }
            // 根据请求的服务名称，通过负载均衡的方式找到一个合适的服务提供者
            // 这里存在一些问题：如果当前服务实列崩了，那么就会出现异常
            Instance instance = loadBalancer.select(instances);

            // 并将该服务的IP地址，端口号返回
            return new InetSocketAddress(instance.getIp(), instance.getPort());
        } catch (NacosException e) {
            logger.error("获取服务时有错误发生:", e);
        }
        return null;
    }

}
